
/**
** \file       exec_element.c
**
** \brief      this function execute element rule
**
** \author     Ben M'rad Hanna, Laterem Hamza, Boillot Ulysse, De Olivera
**             Guillaume and Nguyen Viet Dung
**
** \version    1.0
**
** \date       28 November 2010
**
*/

#include "execution.h"

static char	*my_strcat(char		*s1,
			   char		*s2)
{
  char		*res = NULL;
  int		size1 = 0;
  int		size2 = 0;

  size1 = strlen(s1);
  size2 = strlen(s2);
  res = malloc(size1 + size2 + 1);

  for (int i = 0; i < size1 + size2; ++i)
    {
      if (i < size1)
	res[i] = s1[i];
      else
	res[i] = s2[i - size1];
    }

  free(s1);
  res[size1 + size2] = 0;
  return (res);
}

static char	**change_path2(char	*path)
{
  char          **res = NULL;
  char          *tmp = NULL;
  int           i = 0;
  int           j = 0;
  int           k = 0;

  tmp = malloc(1024);

  while (path[i] != 0)
    {
      j = 0;
      while ((path[i] != ':') && (path[i] != 0))
	{
	  tmp[j] = path[i];
	  ++j;
	  ++i;
	}
      tmp[j] = 0;
      ++i;
      res = realloc(res, (k + 3) * sizeof (char *));
      res[k] = malloc(strlen(tmp) + 1);
      res[k] = strcpy(res[k], tmp);
      ++k;
    }

  res[k] = NULL;
  res[k + 1] = NULL;

  free(tmp);
  return (res);
}

static char	*change_path(char        *binary)
{
  char          *path = NULL;
  int           fd = 0;
  char          **tmp = NULL;
  int           i = 0;

  tmp = change_path2(getenv("PATH"));

  while (tmp[i] != NULL)
    {
      path = my_strcat(my_strcat(tmp[i], "/"), binary);

      if ((fd = open(path, O_RDONLY)) != -1)
	{
	  close(fd);

          for (int k = i + 1; tmp[k] != NULL; ++k)
            free(tmp[k]);
	  free(tmp);

	  return (path);
	}
      free(path);
      ++i;
    }

  for (int k = i; tmp[k] != NULL; ++k)
    free(tmp[k]);
  free(tmp);
  return (NULL);
}

static int      cmd_unknown(char        *binary,
                            char        **argv)
{
  int		size = 0;

  size = strlen(binary);
  write(STDERR_FILENO, "42sh: ", 6);

  for (int i = 0; i < size; ++i)
    write(STDERR_FILENO, &binary[i], 1);

  write(STDERR_FILENO, ": command not found\n", 20);

  free(argv);

  return (1);
}

static int	exec_aux(char	*binary,
			 char	**argv)
{
  int           pid = 0;
  int           status = 0;

  pid = fork();

  if (pid == 0)
    status = execve(binary, argv, g_data->envp);
  else
    waitpid(pid, &status, 0);

  if (status == -1)
    {
      free(binary);
      return (cmd_unknown(binary, argv));
    }


  free(argv);
  free(binary);
  return (0);
}

int             exec_elt(s_element      *node)
{
  char          **argv = NULL;
  char          *binary = NULL;
  s_element     *tmp_node = NULL;
  int           i = 3;

  binary = node->word->word;
  tmp_node = node->next;
  argv = malloc(2 * sizeof (char *));
  argv[0] = binary;
  argv[1] = NULL;

  if ((binary[0] != '/') && (binary[0] != '.'))
    {
      if ((binary = change_path(binary)) == NULL)
	return (cmd_unknown(node->word->word, argv));
    }

  while (tmp_node != NULL)
  {
    argv = realloc(argv, i * sizeof (char *));
    if (tmp_node->word != NULL)
      argv[i - 2] = tmp_node->word->word;
    argv[i - 1] = NULL;
    tmp_node = tmp_node->next;
    ++i;
  }

  i = exec_aux(binary, argv);
  return (i);
}
